package com.haixiaoke.saas.user.service.impl;

import java.util.*;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.haixiaoke.saas.common.constant.AppConstants;
import com.haixiaoke.saas.common.constant.DeviceLockConstants;
import com.haixiaoke.saas.common.constant.UserConstants;
import com.haixiaoke.saas.common.core.redis.RedisCache;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.common.utils.sign.Md5Utils;
import com.haixiaoke.saas.common.weChat.domain.WeChatLoginParam;
import com.haixiaoke.saas.lock.domain.Group;
import com.haixiaoke.saas.lock.domain.LockFace;
import com.haixiaoke.saas.lock.domain.LockOperatingRecord;
import com.haixiaoke.saas.lock.domain.LockPwd;
import com.haixiaoke.saas.lock.service.*;
import com.haixiaoke.saas.lock.service.impl.LockDevicesService;
import com.haixiaoke.saas.system.domain.LoginBody;
import com.haixiaoke.saas.system.framework.security.util.SecurityUtils;
import com.haixiaoke.saas.system.framework.web.service.SysLoginService;
import com.haixiaoke.saas.user.HomePageVo;
import com.haixiaoke.saas.user.domain.User;
import com.haixiaoke.saas.user.mapper.UserMapper;
import com.haixiaoke.saas.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 用户Service业务层处理
 *
 * @author xiaolong
 * @date 2025-04-01
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private SysLoginService sysLoginService;
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ILockFaceService lockFaceService;
    @Autowired
    private ILockPwdService lockPwdService;
    @Autowired
    private LockDevicesService lockDevicesService;
    @Autowired
    private ILockOperatingRecordService lockOperatingRecordService;
    @Autowired
    private IGroupService groupService;
    @Autowired
    private IDeviceLockService deviceLockService;
    @Resource
    private RedisCache redisCache;
    /**
     * 查询用户
     *
     * @param userId 用户主键
     * @return 用户
     */
    @Override
    public User selectUserByUserId(Long userId) {
        return userMapper.selectUserByUserId(userId);
    }

    /**
     * 查询用户列表
     *
     * @param user 用户
     * @return 用户
     */
    @Override
    public List<User> selectUserList(User user) {
        return userMapper.selectUserList(user);
    }

    /**
     * 新增用户
     *
     * @param user 用户
     * @return 结果
     */
    @Override
    public int insertUser(User user) {
        user.setCreateTime(DateUtils.getNowDate());
        return userMapper.insertUser(user);
    }

    /**
     * 修改用户、手机号
     *
     * @param user 用户
     * @return 结果
     */
    @Override
    public int updateUser(User user) {
        if (StrUtil.isEmpty(user.getPhone())) {
            throw new ServiceException("手机号不能为空");
        }
        if (!Validator.isMobile(user.getPhone())) {
            throw new ServiceException("手机号格式不正确");
        }
        user.setUpdateTime(DateUtils.getNowDate());
        return userMapper.updateUser(user);
    }

    /**
     * 批量删除用户
     *
     * @param userIds 需要删除的用户主键
     * @return 结果
     */
    @Override
    public int deleteUserByUserIds(Long[] userIds) {
        return userMapper.deleteUserByUserIds(userIds);
    }

    /**
     * 删除用户信息
     *
     * @param userId 用户主键
     * @return 结果
     */
    @Override
    public int deleteUserByUserId(Long userId) {
        return userMapper.deleteUserByUserId(userId);
    }

    @Override
    @Transactional
    public User weChatSelectUserByPhone(WeChatLoginParam loginParam) {
        String code = loginParam.getCode();
        String encryptedData = loginParam.getEncryptedData();
        String iv = loginParam.getIv();

        WxMaJscode2SessionResult session = null;
        try {
            session = wxMaService.getUserService().getSessionInfo(code);
        } catch (WxErrorException e) {
            throw new ServiceException("登录异常：" + e.getLocalizedMessage());
        }
        String openid = session.getOpenid();

        String sessionKey = session.getSessionKey();
        WxMaPhoneNumberInfo phoneNoInfo = null;
        try {
            phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        } catch (Exception e) {
            log.error("数据映射异常:{},{},{}", code, encryptedData, iv, e);
            throw new ServiceException("登录异常,请重新登录");
        }
        String phoneNumber = phoneNoInfo.getPhoneNumber();
        if (StrUtil.isBlank(phoneNumber)) {
            throw new ServiceException("手机号码为空");
        }
        User user = userMapper.selectUserByPhone(phoneNumber);
        Date nowDate = DateUtils.getNowDate();
        if (ObjectUtil.isEmpty(user)) {
            User newUser = new User();
            newUser.setPhone(phoneNumber);
            newUser.setNickName("未命名");
            newUser.setOpenId(openid);
            newUser.setCreateTime(nowDate);
            newUser.setLastLoginTime(nowDate);
            userMapper.insertUser(newUser);

            Group group = new Group();
            group.setGroupName("默认");
            group.setUserId(newUser.getUserId());
            group.setGroupType(DeviceLockConstants.GROUP_TYPE_NON_DEFAULT);
            group.setCreateBy(phoneNumber);
            groupService.insertGroup(group);
            return newUser;
        } else {
            // 如果用户被禁用，则禁止登录
            if (UserConstants.ACCOUNT_STATUS_DISABLE.equals(user.getAccountStatus())) {
                throw new ServiceException("账号已被禁用，请联系管理员");
            }
            user.setOpenId(openid);
            user.setUpdateTime(nowDate);
            user.setLastLoginTime(nowDate);
            userMapper.updateUser(user);
            return user;
        }
    }

    @Override
    @Transactional
    public int register(User user) {
        if (StrUtil.isEmpty(user.getPhone()) || StrUtil.isEmpty(user.getCode()) ||
                StrUtil.isEmpty(user.getPassword()) || StrUtil.isEmpty(user.getAgainPassword())) {
            throw new ServiceException("数据不完整");
        }
        sysLoginService.validateMobileCaptcha(user.getPhone(), user.getCode(), true);
        if (!Validator.isMobile(user.getPhone())) {
            throw new ServiceException("手机号格式不正确");
        }
        if (!user.getPassword().equals(user.getAgainPassword())) {
            throw new ServiceException("两次密码不一致");
        }
        if (user.getPassword().length() < 6 || user.getPassword().length() > 20) {
            throw new ServiceException("密码长度必须在6-20位之间");
        }
        User sqlUser = userMapper.selectUserByPhone(user.getPhone());
        if (ObjectUtil.isEmpty(sqlUser)) {
            User newUser = new User();
            newUser.setPhone(user.getPhone());
            newUser.setNickName("未命名");
            newUser.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
            newUser.setCreateTime(DateUtils.getNowDate());
            int i = userMapper.insertUser(newUser);

            if (i > 0) {
                Group group = new Group();
                group.setGroupName("默认");
                group.setUserId(newUser.getUserId());
                group.setGroupType(DeviceLockConstants.GROUP_TYPE_NON_DEFAULT);
                group.setCreateBy(newUser.getPhone());
                groupService.insertGroup(group);
            }
            return i;
        } else {
            sqlUser.setUpdateTime(DateUtils.getNowDate());
            sqlUser.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
            return userMapper.updateUser(sqlUser);
        }
    }

    @Override
    public int setPassword(User user) {
        return updateUserPassword(user);

    }

    @Override
    public int resetPassword(User user) {
        return updateUserPassword(user);
    }

    @Override
    public User selectUserByPhoneAndPassword(LoginBody loginBody) {
        // 校验手机号
        String phone = loginBody.getPhone();
        checkParameter(phone);
        // 校验验证码
        loginService.validateCaptcha(phone, loginBody.getCode(), loginBody.getUuid(), true);

        User user = userMapper.selectUserByPhone(phone);
        if (ObjectUtil.isEmpty(user)) {
            throw new ServiceException("用户不存在");
        } else {
            // 如果用户被禁用，则禁止登录
            if (UserConstants.ACCOUNT_STATUS_DISABLE.equals(user.getAccountStatus())) {
                throw new ServiceException("账号已被禁用，请联系管理员");
            }
        }
        if (StrUtil.isEmpty(loginBody.getPassword())) {
            throw new ServiceException("密码不能为空");
        }
        if (!SecurityUtils.matchesPassword(loginBody.getPassword(), user.getPassword())) {
            throw new ServiceException("密码错误");
        }
        user.setLastLoginTime(DateUtils.getNowDate());
        userMapper.updateUser(user);
        return user;
    }

    @Override
    @Transactional
    public User selectUserByCaptcha(LoginBody loginBody) {
        String phone = loginBody.getPhone();
        checkParameter(phone);
        // 验证码校验
        sysLoginService.validateMobileCaptcha(phone, loginBody.getCode(), true);
        User user = userMapper.selectUserByPhone(phone);
        Date nowDate = DateUtils.getNowDate();
        if (ObjectUtil.isEmpty(user)) {
            User newUser = new User();
            newUser.setPhone(phone);
            newUser.setNickName("未命名");
            newUser.setCreateTime(nowDate);
            newUser.setLastLoginTime(nowDate);
            int i = userMapper.insertUser(newUser);

            if (i > 0) {
                Group group = new Group();
                group.setGroupName("默认");
                group.setUserId(newUser.getUserId());
                group.setGroupType(DeviceLockConstants.GROUP_TYPE_NON_DEFAULT);
                group.setCreateBy(newUser.getPhone());
                groupService.insertGroup(group);
            }
            return newUser;
        } else {
            // 如果用户被禁用，则禁止登录
            if (UserConstants.ACCOUNT_STATUS_DISABLE.equals(user.getAccountStatus())) {
                throw new ServiceException("账号已被禁用，请联系管理员");
            }
            user.setLastLoginTime(nowDate);
            userMapper.updateUser(user);
            return user;
        }


    }

    @Override
    public User selectUserByPhone(String phone) {
        return userMapper.selectUserByPhone(phone);
    }

    @Override
    @Transactional
    public int logoutUser(Long userId, String userName) {
        User user = userMapper.selectUserByUserIdAndAccountStatus(userId);
        if (ObjectUtil.isEmpty(user)) {
            throw new ServiceException("用户不存在或用户已经注销");
        }
        List<LockFace> lockFaceList;
        List<LockOperatingRecord> lockOperatingRecordList = new ArrayList<>();
        Date nowDate = DateUtils.getNowDate();
        lockFaceList = lockFaceService.selectLockFaceByAuthRoleTypeAndUserId(DeviceLockConstants.AUTH_ROLE_TYPE_MAIN_ADMIN, userId);
        if (CollectionUtil.isNotEmpty(lockFaceList)) {
            throw new ServiceException("账号有设备未删除,请解绑后操作");
        }

        // 删除授权信息
        lockFaceList = lockFaceService.selectLockFaceByUserId(userId);
        if (CollectionUtil.isNotEmpty(lockFaceList)) {
            for (LockFace lockFace : lockFaceList) {
                // 删除锁人脸授权
                if (DeviceLockConstants.LOCK_STATE_ENABLE.equals(lockFace.getFaceState())) {
                    lockDevicesService.removeFace(lockFace.getLockMac(), lockFace.getIdentification());
                }

                // 锁操作记录
                LockOperatingRecord lockOperatingRecord = new LockOperatingRecord();
                lockOperatingRecord.setLockId(lockFace.getLockId());
                lockOperatingRecord.setOperatingType(DeviceLockConstants.OPERATING_TYPE_DELETE);
                lockOperatingRecord.setOperatingContent("删除授权：" + lockFace.getUserName());
                lockOperatingRecord.setCreateBy(StrUtil.isBlank(user.getUserName()) ? user.getPhone() : user.getUserName());
                lockOperatingRecord.setCreateTime(nowDate);
                lockOperatingRecordList.add(lockOperatingRecord);
            }
            lockFaceService.softDeleteLockFaceByUserId(userId);
        }
        List<LockPwd> lockPwdList = lockPwdService.selectLockPwdByUserId(userId);
        if (CollectionUtil.isNotEmpty(lockPwdList)) {
            for (LockPwd lockPwd : lockPwdList) {
                // 删除锁密码授权
                if (DeviceLockConstants.LOCK_STATE_ENABLE.equals(lockPwd.getPwdState())) {
                    lockDevicesService.removeLockPwd(lockPwd.getLockMac(), lockPwd.getIdentification());
                }

                // 锁操作记录
                LockOperatingRecord lockOperatingRecord = new LockOperatingRecord();
                lockOperatingRecord.setLockId(lockPwd.getLockId());
                lockOperatingRecord.setOperatingType(DeviceLockConstants.OPERATING_TYPE_DELETE);
                lockOperatingRecord.setOperatingContent("删除密码：" + lockPwd.getLockId());
                lockOperatingRecord.setCreateBy(StrUtil.isBlank(user.getUserName()) ? user.getPhone() : user.getUserName());
                lockOperatingRecord.setCreateTime(nowDate);
                lockOperatingRecordList.add(lockOperatingRecord);
            }
            lockPwdService.softDeleteLockPwdByUserId(userId);
        }

        if (CollectionUtil.isNotEmpty(lockOperatingRecordList)) {
            lockOperatingRecordService.batchInsertLockOperatingRecord(lockOperatingRecordList);
        }
        user.setUpdateTime(nowDate);
        user.setUpdateBy(userName);
        user.setAccountStatus(UserConstants.ACCOUNT_STATUS_LOGOUT);
        return userMapper.updateUser(user);
    }

    @Override
    public List<User> selectUserByPhoneList(List<String> phoneList) {
        return userMapper.selectUserByPhoneList(phoneList);
    }

    @Override
    public int editUser(User user) {
        user.setUpdateTime(DateUtils.getNowDate());
        return userMapper.updateUser(user);
    }

    @Override
    public int updateUserAccountStatus(Long userId, String userName) {
        User user = userMapper.selectUserByUserIdAndAccountStatus(userId);
        if (ObjectUtil.isEmpty(user)) {
            throw new ServiceException("用户不存在或用户已经注销");
        }
        if (UserConstants.ACCOUNT_STATUS_DISABLE.equals(user.getAccountStatus())) {
            user.setAccountStatus(UserConstants.ACCOUNT_STATUS_NORMAL);
        } else {
            user.setAccountStatus(UserConstants.ACCOUNT_STATUS_DISABLE);
        }
        user.setUpdateTime(DateUtils.getNowDate());
        user.setUpdateBy(userName);
        int i = userMapper.updateUser(user);

        // 删除token
        if (UserConstants.ACCOUNT_STATUS_DISABLE.equals(user.getAccountStatus()) && (i > 0)) {
            redisCache.deleteObject(AppConstants.USER_TOKEN_REDIS_KEY_PREFIX + Md5Utils.hash(user.getUserId() + user.getPhone() + "@"));
        }
        return i;
    }

    @Override
    public HomePageVo homePage() {
        HomePageVo homePageVo = userMapper.homePageCount();;
        Map<String, Map<String, Object>> deviceLockMap = deviceLockService.homePageCountOnlineStatus();
        Map<String, Object> orderStateMapNew = new HashMap<>();
        orderStateMapNew.put(DeviceLockConstants.ONLINE_STATUS_ONLINE, 0L);
        orderStateMapNew.put(DeviceLockConstants.ONLINE_STATUS_OFFLINE, 0L);
        for (Map.Entry<String, Map<String, Object>> entry : deviceLockMap.entrySet()) {
            orderStateMapNew.put(entry.getKey(), entry.getValue().get("num"));
        }

        // 安全地获取在线和离线数量
        Long online = getLongValue(orderStateMapNew, DeviceLockConstants.ONLINE_STATUS_ONLINE);
        Long offline = getLongValue(orderStateMapNew, DeviceLockConstants.ONLINE_STATUS_OFFLINE);

        Long amount = online + offline;
        orderStateMapNew.put("amount", amount);
        homePageVo.setDeviceLockMap(orderStateMapNew);

        List<Map<String, Object>> newTodayMap = userMapper.countNewUser();
        homePageVo.setNewTodayList(newTodayMap);
        return homePageVo;
    }

    private void checkParameter(String phone) {
        if (StrUtil.isEmpty(phone)) {
            throw new ServiceException("手机号不能为空");
        }
        if (!Validator.isMobile(phone)) {
            throw new ServiceException("手机号格式不正确");
        }

    }

    // 辅助方法：安全获取Long值
    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value instanceof Long) {
            return (Long) value;
        } else if (value instanceof Number) {
            return ((Number) value).longValue();
        } else if (value != null) {
            try {
                return Long.parseLong(value.toString());
            } catch (NumberFormatException e) {
                return 0L;
            }
        }
        return 0L;
    }


    /**
     * 更新用户密码
     *
     * @param user 用户
     * @return 结果
     */
    private int updateUserPassword(User user) {
        if (StrUtil.isEmpty(user.getPassword()) || StrUtil.isEmpty(user.getAgainPassword())) {
            throw new ServiceException("密码不能为空");
        }
        if (!user.getPassword().equals(user.getAgainPassword())) {
            throw new ServiceException("两次密码不一致");
        }
        if (user.getPassword().length() < 6 || user.getPassword().length() > 20) {
            throw new ServiceException("密码长度必须在6-20位之间");
        }
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateTime(DateUtils.getNowDate());
        return userMapper.updateUser(user);
    }


}

